package vn.conghuy.talkwithme.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class Utils {
	
	private static final String[] keywordNeedReplace = {" with", " with ", " and", " and "};
	
	public static String requestHtmlContent(String sUrl){
		URL url;
		try {
			url = new URL( sUrl );
		
	        InputStream is = url.openConnection().getInputStream();
	
	        BufferedReader reader = new BufferedReader( new InputStreamReader( is )  );
	
	        String line = null;
	        StringBuilder strBuilder = new StringBuilder();
	
	        while( ( line = reader.readLine() ) != null )  {
	        	strBuilder.append(line +"\n");
	        }
	        reader.close();
	        
	        return strBuilder.toString();
	        
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Document stringToDom(String xmlSource) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
		try {
			builder = factory.newDocumentBuilder();
			return builder.parse(new InputSource(new StringReader(xmlSource)));
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
        return null;
    }
	
	public static boolean isExistElemInArrayIsSubStringOfStr(String[] arrStr, String str){
		for(String s : arrStr){
			if(str.contains(s))
				return true;
		}
		return false;
	}
	
	public static boolean isExistElemInArrayIsSubStringOfStr(String[] arrStr, String str, StringWrapper outStr){
		for(String s : arrStr){
			if(str.contains(s))
			{
				outStr.setStr(s);
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Check if exist an element in array be a word in specified string
	 * @param arrStr contain words to compare with string.
	 * @param str string specified
	 * @return exist or not
	 */
	public static boolean isExistElemInArrayIsWordOfStr(String[] arrStr, String str, StringWrapper outStr){
		//TODO not done
		for(String s : arrStr){
			if(indexOfWord(str, s) != -1){
				if(outStr != null) outStr.setStr(s);
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Check if exist an element in array be a word in specified string
	 * @param arrStr contain words to compare with string.
	 * @param str string specified
	 * @return exist or not
	 */
	public static boolean isExistElemInArrayIsWordOfStr(ArrayList<String> arrStr, String str, StringWrapper outStr){
		//TODO not done
		for(String s : arrStr){
			if(indexOfWord(str, s) != -1){
				if(outStr != null) outStr.setStr(s);
				return true;
			}
		}
		return false;
	}
	
	public static boolean isExistStringInArray(String[] arrStr, String str){
		for(String s : arrStr){
			if(str.equalsIgnoreCase(s))
				return true;
		}
		return false;
	}
	
	public static boolean isStringBeSubStringOfAnElementInArray(String str, String[] arrStr){
		for(String s : arrStr){
			if(s.contains(str))
				return true;
		}
		
		return false;
	}
	
	private static String wordToNumber(String word){
		if(word.equals("oh") || word.equals("zero"))
			return "0";
		else if(word.equals("one"))
			return "1";
		else if(word.equals("two"))
			return "2";
		else if(word.equals("three"))
			return "3";
		else if(word.equals("four"))
			return "4";
		else if(word.equals("five"))
			return "5";
		else if(word.equals("six"))
			return "6";
		else if(word.equals("seven"))
			return "7";
		else if(word.equals("eight"))
			return "8";
		else if(word.equals("nine"))
			return "9";
		else return null;
	}
	
	public static String numberFromString(String str){
		String[] words = str.split(" ");
		String numberArray = "";
		for(String word : words){
			//find number write by numeral, example "123"
			Pattern p = Pattern.compile("(([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))");
			Matcher m = p.matcher(word);
			if(m.find()){
				String result = m.group();
				numberArray = result;
				return numberArray;
			}
			
			// if not match numeral, check word match with alphabetical
			String number = wordToNumber(word);
			if(number != null){
				numberArray += number;
			}
			else{
				if(numberArray.equals("") == false)
					break;
			}
		}
		return numberArray;
	}
	
	public static String getRandomString(String[] arString){
		Random randomGenerator = new Random();
		int index = randomGenerator.nextInt(arString.length);
		return arString[index];
	}
	
	public static boolean isTextBePlain(String text){
		if(text.contains("<img src=") && text.contains("</img>")){
			return false;
		}
		else return true;
	}
	
	public static boolean hasNumber(String str, IntWrapper outInt){
		String[] words = str.split(" ");
		for(String word:words){
			try{
				int num = Integer.parseInt(word);
				if(outInt != null) outInt.setInt(num);
				return true;
			}
			catch (NumberFormatException ex){
			}
		}
		return false;
	}
	
	public static boolean isNumber(String str, IntWrapper outInt){
		try{
			int num = Integer.parseInt(str);
			if(outInt != null) outInt.setInt(num);
			return true;
		}
		catch (NumberFormatException ex){
			return false;
		}
	}
	
public static int lastIndexOfWord(String origin, String word){
		
		int index = origin.lastIndexOf(word);
		while(index != -1){
			char[] chArray = origin.toCharArray();
			int indexBefore = index - 1;
			int indexAfter = index + word.length();
			if(indexBefore < 0 || (indexBefore > 0 && chArray[indexBefore] == ' ')
					&& (indexAfter >= origin.length() || (indexBefore < origin.length() && chArray[indexAfter] == ' '))){
				return index;
			}
			origin = origin.substring(0, index - 1);
			index = origin.lastIndexOf(word);
		}
		return -1;
		
	}
	
	public static int indexOfWord(String origin, String word){

		int index = origin.indexOf(word);
		char[] chArray = origin.toCharArray();
		while(index != -1){
			
			int indexBefore = index - 1;
			int indexAfter = index + word.length();
			if((index == 0 || (index > 0 && chArray[indexBefore] == ' '))
					&& (indexAfter >= origin.length() || (indexAfter < origin.length() && chArray[indexAfter] == ' '))){
				return index;
			}
			
			index = origin.indexOf(word, index + word.length());
		}
		return -1;
	}
	/**
	 * Find the smallest number but bigger standard number in follow numbers
	 * @param standardNumber number to other compare with
	 * @param compareNumbers numbers will be compare with standard number
	 * @return the number smallest but bigger standard number
	 */
	public static int firstGreaterThanNumber(int standardNumber, int... compareNumbers){
		Arrays.sort(compareNumbers);
		for(int num:compareNumbers){
			if(num > standardNumber)
				return num;
		}
		return -1;
	}
		
	/**
	 * Standardize phrase by replace "with", "and", ... keyword in the end of phrase
	 * @param phrase phrase need to standardize
	 * @return phrase standardized
	 */
	public static String standardizePhrase(String phrase){
		String sEnd = null;
		for(String word:keywordNeedReplace){
			if(phrase.endsWith(word)){
				sEnd = word;
				break;
			}
		}
		
		if(sEnd != null){
			String result = phrase.substring(0, phrase.length() - sEnd.length());
			return result;
		}
		else return phrase;
	}
	
	public static String normalizeString(String input){
		while (input.indexOf("  ") != -1) input = input.replaceAll("  "," ");
		return input;
	}
	
	public static boolean isStringMatchRegexInArray(String str, String[] regexex){
		for(String regex:regexex){
			Pattern pattern = Pattern.compile(regex);
			Matcher matcher = pattern.matcher(str);
			if(matcher.matches()) return true;
		}
		return false;
	}
}
